{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 分组变换和分析\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import random\n",
    "import string\n",
    "import tushare as ts # Yahoo的接口不能指望了\n",
    "from pandas import DataFrame, Series\n",
    "from pandas.tseries.offsets import Day, Hour, Minute, MonthEnd\n",
    "from sklearn.linear_model import LinearRegression\n",
    "\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['MQNCX', 'IJYOS', 'CTAMU', 'DAANV', 'PAQJB', 'FBHXO', 'NRXGH',\n",
       "       'BBTFB', 'WEZHG', 'VSJOL'],\n",
       "      dtype='<U5')"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "N = 1000\n",
    "def rands(n):\n",
    "  choices = string.ascii_uppercase\n",
    "  return ''.join([random.choice(choices) for _ in range(n)])\n",
    "tickers = np.array([rands(5) for _ in range(N)])\n",
    "tickers[:10] # 随机生成1000个股票代码，显示前10个。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Momentum</th>\n",
       "      <th>ShortInterest</th>\n",
       "      <th>Value</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>MQNCX</th>\n",
       "      <td>0.033327</td>\n",
       "      <td>-0.022390</td>\n",
       "      <td>0.080698</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>IJYOS</th>\n",
       "      <td>0.045715</td>\n",
       "      <td>-0.018835</td>\n",
       "      <td>0.093913</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>CTAMU</th>\n",
       "      <td>0.030443</td>\n",
       "      <td>-0.014324</td>\n",
       "      <td>0.073361</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>DAANV</th>\n",
       "      <td>0.021882</td>\n",
       "      <td>-0.012971</td>\n",
       "      <td>0.079016</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>PAQJB</th>\n",
       "      <td>0.030116</td>\n",
       "      <td>-0.025061</td>\n",
       "      <td>0.079561</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       Momentum  ShortInterest     Value\n",
       "MQNCX  0.033327      -0.022390  0.080698\n",
       "IJYOS  0.045715      -0.018835  0.093913\n",
       "CTAMU  0.030443      -0.014324  0.073361\n",
       "DAANV  0.021882      -0.012971  0.079016\n",
       "PAQJB  0.030116      -0.025061  0.079561"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M = 500\n",
    "df = DataFrame({'Momentum' : np.random.randn(M) / 200 + 0.03,\n",
    "                'Value' : np.random.randn(M) / 200 + 0.08,\n",
    "                'ShortInterest' : np.random.randn(M) / 200 - 0.02},\n",
    "               index=tickers[:M])\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "MQNCX         TECH\n",
       "IJYOS    FINANCIAL\n",
       "CTAMU         TECH\n",
       "DAANV         TECH\n",
       "PAQJB         TECH\n",
       "Name: industry, dtype: object"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ind_names = np.array(['FINANCIAL', 'TECH'])\n",
    "sampler = np.random.randint(0, len(ind_names), N)\n",
    "industries = Series(ind_names[sampler],\n",
    "                    index=tickers,\n",
    "                    name='industry')\n",
    "industries.head() # 随机给公司分类，financial或tech。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Momentum</th>\n",
       "      <th>ShortInterest</th>\n",
       "      <th>Value</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>industry</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>FINANCIAL</th>\n",
       "      <td>0.030235</td>\n",
       "      <td>-0.020340</td>\n",
       "      <td>0.079965</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>TECH</th>\n",
       "      <td>0.030338</td>\n",
       "      <td>-0.019692</td>\n",
       "      <td>0.079927</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "           Momentum  ShortInterest     Value\n",
       "industry                                    \n",
       "FINANCIAL  0.030235      -0.020340  0.079965\n",
       "TECH       0.030338      -0.019692  0.079927"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "by_industry = df.groupby(industries)\n",
    "by_industry.mean() # 计算按行业分组的平均值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th colspan=\"8\" halign=\"left\">Momentum</th>\n",
       "      <th colspan=\"5\" halign=\"left\">ShortInterest</th>\n",
       "      <th colspan=\"8\" halign=\"left\">Value</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>std</th>\n",
       "      <th>min</th>\n",
       "      <th>25%</th>\n",
       "      <th>50%</th>\n",
       "      <th>75%</th>\n",
       "      <th>max</th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>...</th>\n",
       "      <th>75%</th>\n",
       "      <th>max</th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>std</th>\n",
       "      <th>min</th>\n",
       "      <th>25%</th>\n",
       "      <th>50%</th>\n",
       "      <th>75%</th>\n",
       "      <th>max</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>industry</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>FINANCIAL</th>\n",
       "      <td>230.0</td>\n",
       "      <td>0.030235</td>\n",
       "      <td>0.004861</td>\n",
       "      <td>0.018799</td>\n",
       "      <td>0.027297</td>\n",
       "      <td>0.029913</td>\n",
       "      <td>0.032982</td>\n",
       "      <td>0.046882</td>\n",
       "      <td>230.0</td>\n",
       "      <td>-0.020340</td>\n",
       "      <td>...</td>\n",
       "      <td>-0.017302</td>\n",
       "      <td>-0.006896</td>\n",
       "      <td>230.0</td>\n",
       "      <td>0.079965</td>\n",
       "      <td>0.005032</td>\n",
       "      <td>0.064342</td>\n",
       "      <td>0.076482</td>\n",
       "      <td>0.079450</td>\n",
       "      <td>0.083322</td>\n",
       "      <td>0.094006</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>TECH</th>\n",
       "      <td>270.0</td>\n",
       "      <td>0.030338</td>\n",
       "      <td>0.004785</td>\n",
       "      <td>0.017966</td>\n",
       "      <td>0.027037</td>\n",
       "      <td>0.030376</td>\n",
       "      <td>0.033564</td>\n",
       "      <td>0.043232</td>\n",
       "      <td>270.0</td>\n",
       "      <td>-0.019692</td>\n",
       "      <td>...</td>\n",
       "      <td>-0.016145</td>\n",
       "      <td>-0.004464</td>\n",
       "      <td>270.0</td>\n",
       "      <td>0.079927</td>\n",
       "      <td>0.005413</td>\n",
       "      <td>0.059576</td>\n",
       "      <td>0.076253</td>\n",
       "      <td>0.079672</td>\n",
       "      <td>0.083438</td>\n",
       "      <td>0.093884</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>2 rows × 24 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "          Momentum                                                    \\\n",
       "             count      mean       std       min       25%       50%   \n",
       "industry                                                               \n",
       "FINANCIAL    230.0  0.030235  0.004861  0.018799  0.027297  0.029913   \n",
       "TECH         270.0  0.030338  0.004785  0.017966  0.027037  0.030376   \n",
       "\n",
       "                              ShortInterest              ...               \\\n",
       "                75%       max         count      mean    ...          75%   \n",
       "industry                                                 ...                \n",
       "FINANCIAL  0.032982  0.046882         230.0 -0.020340    ...    -0.017302   \n",
       "TECH       0.033564  0.043232         270.0 -0.019692    ...    -0.016145   \n",
       "\n",
       "                     Value                                                    \\\n",
       "                max  count      mean       std       min       25%       50%   \n",
       "industry                                                                       \n",
       "FINANCIAL -0.006896  230.0  0.079965  0.005032  0.064342  0.076482  0.079450   \n",
       "TECH      -0.004464  270.0  0.079927  0.005413  0.059576  0.076253  0.079672   \n",
       "\n",
       "                               \n",
       "                75%       max  \n",
       "industry                       \n",
       "FINANCIAL  0.083322  0.094006  \n",
       "TECH       0.083438  0.093884  \n",
       "\n",
       "[2 rows x 24 columns]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "by_industry.describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def zscore(group):\n",
    "  return (group - group.mean()) / group.std()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Momentum</th>\n",
       "      <th>ShortInterest</th>\n",
       "      <th>Value</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>MQNCX</th>\n",
       "      <td>0.624594</td>\n",
       "      <td>-0.539440</td>\n",
       "      <td>0.142331</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>IJYOS</th>\n",
       "      <td>3.184773</td>\n",
       "      <td>0.314931</td>\n",
       "      <td>2.771779</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>CTAMU</th>\n",
       "      <td>0.021955</td>\n",
       "      <td>1.073453</td>\n",
       "      <td>-1.212983</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>DAANV</th>\n",
       "      <td>-1.767286</td>\n",
       "      <td>1.344028</td>\n",
       "      <td>-0.168335</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>PAQJB</th>\n",
       "      <td>-0.046455</td>\n",
       "      <td>-1.073684</td>\n",
       "      <td>-0.067583</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       Momentum  ShortInterest     Value\n",
       "MQNCX  0.624594      -0.539440  0.142331\n",
       "IJYOS  3.184773       0.314931  2.771779\n",
       "CTAMU  0.021955       1.073453 -1.212983\n",
       "DAANV -1.767286       1.344028 -0.168335\n",
       "PAQJB -0.046455      -1.073684 -0.067583"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_stand = by_industry.apply(zscore) # 每个股票减去所在分组的平均值再除标准差\n",
    "df_stand.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th colspan=\"2\" halign=\"left\">Momentum</th>\n",
       "      <th colspan=\"2\" halign=\"left\">ShortInterest</th>\n",
       "      <th colspan=\"2\" halign=\"left\">Value</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th>mean</th>\n",
       "      <th>std</th>\n",
       "      <th>mean</th>\n",
       "      <th>std</th>\n",
       "      <th>mean</th>\n",
       "      <th>std</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>industry</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>FINANCIAL</th>\n",
       "      <td>4.962818e-16</td>\n",
       "      <td>1.0</td>\n",
       "      <td>2.280302e-15</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1.915316e-14</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>TECH</th>\n",
       "      <td>7.822960e-16</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-1.085551e-16</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-2.607970e-15</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "               Momentum      ShortInterest              Value     \n",
       "                   mean  std          mean  std          mean  std\n",
       "industry                                                          \n",
       "FINANCIAL  4.962818e-16  1.0  2.280302e-15  1.0  1.915316e-14  1.0\n",
       "TECH       7.822960e-16  1.0 -1.085551e-16  1.0 -2.607970e-15  1.0"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_stand.groupby(industries).agg(['mean', 'std']) # 显然均值为0，标准差为1。看下zscore公式就明白了。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Momentum</th>\n",
       "      <th>ShortInterest</th>\n",
       "      <th>Value</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>MQNCX</th>\n",
       "      <td>76.0</td>\n",
       "      <td>188.0</td>\n",
       "      <td>114.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>IJYOS</th>\n",
       "      <td>2.0</td>\n",
       "      <td>84.0</td>\n",
       "      <td>2.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>CTAMU</th>\n",
       "      <td>134.0</td>\n",
       "      <td>38.0</td>\n",
       "      <td>243.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>DAANV</th>\n",
       "      <td>260.0</td>\n",
       "      <td>25.0</td>\n",
       "      <td>152.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>PAQJB</th>\n",
       "      <td>143.0</td>\n",
       "      <td>234.0</td>\n",
       "      <td>142.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       Momentum  ShortInterest  Value\n",
       "MQNCX      76.0          188.0  114.0\n",
       "IJYOS       2.0           84.0    2.0\n",
       "CTAMU     134.0           38.0  243.0\n",
       "DAANV     260.0           25.0  152.0\n",
       "PAQJB     143.0          234.0  142.0"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ind_rank = by_industry.rank(ascending=False)\n",
    "ind_rank.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th colspan=\"2\" halign=\"left\">Momentum</th>\n",
       "      <th colspan=\"2\" halign=\"left\">ShortInterest</th>\n",
       "      <th colspan=\"2\" halign=\"left\">Value</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th>min</th>\n",
       "      <th>max</th>\n",
       "      <th>min</th>\n",
       "      <th>max</th>\n",
       "      <th>min</th>\n",
       "      <th>max</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>industry</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>FINANCIAL</th>\n",
       "      <td>1.0</td>\n",
       "      <td>230.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>230.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>230.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>TECH</th>\n",
       "      <td>1.0</td>\n",
       "      <td>270.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>270.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>270.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          Momentum        ShortInterest        Value       \n",
       "               min    max           min    max   min    max\n",
       "industry                                                   \n",
       "FINANCIAL      1.0  230.0           1.0  230.0   1.0  230.0\n",
       "TECH           1.0  270.0           1.0  270.0   1.0  270.0"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ind_rank.groupby(industries).agg(['min', 'max'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Momentum</th>\n",
       "      <th>ShortInterest</th>\n",
       "      <th>Value</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>MQNCX</th>\n",
       "      <td>0.761976</td>\n",
       "      <td>-0.672331</td>\n",
       "      <td>0.275336</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>IJYOS</th>\n",
       "      <td>1.705755</td>\n",
       "      <td>0.473403</td>\n",
       "      <td>1.705755</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>CTAMU</th>\n",
       "      <td>0.019209</td>\n",
       "      <td>1.248615</td>\n",
       "      <td>-1.376679</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>DAANV</th>\n",
       "      <td>-1.594386</td>\n",
       "      <td>1.415098</td>\n",
       "      <td>-0.211304</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>PAQJB</th>\n",
       "      <td>-0.096047</td>\n",
       "      <td>-1.261422</td>\n",
       "      <td>-0.083241</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       Momentum  ShortInterest     Value\n",
       "MQNCX  0.761976      -0.672331  0.275336\n",
       "IJYOS  1.705755       0.473403  1.705755\n",
       "CTAMU  0.019209       1.248615 -1.376679\n",
       "DAANV -1.594386       1.415098 -0.211304\n",
       "PAQJB -0.096047      -1.261422 -0.083241"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "by_industry.apply(lambda x: zscore(x.rank())).head() # 标准化排名数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 分组因子暴露"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['DMIQP', 'VZJDZ', 'JZISA', 'BRGLD', 'MNRHS', 'PPCPE', 'KWSMF',\n",
       "       'NHPNA', 'ZTUMI', 'BNBRW'],\n",
       "      dtype='<U5')"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fac1, fac2, fac3 = np.random.rand(3, 1000)\n",
    "ticker_subset = tickers.take(np.random.permutation(N)[:1000])\n",
    "ticker_subset[:10]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DMIQP    0.489926\n",
       "VZJDZ    1.183795\n",
       "JZISA    0.866891\n",
       "BRGLD    0.316336\n",
       "MNRHS    0.132618\n",
       "dtype: float64"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "port = Series(0.7 * fac1 - 1.2 * fac2 + 0.3 * fac3 + np.random.rand(1000),\n",
    "              index=ticker_subset)\n",
    "port.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>f1</th>\n",
       "      <th>f2</th>\n",
       "      <th>f3</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>DMIQP</th>\n",
       "      <td>0.149764</td>\n",
       "      <td>0.530645</td>\n",
       "      <td>0.568934</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>VZJDZ</th>\n",
       "      <td>0.650494</td>\n",
       "      <td>0.085542</td>\n",
       "      <td>0.449133</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>JZISA</th>\n",
       "      <td>0.959627</td>\n",
       "      <td>0.070090</td>\n",
       "      <td>0.220922</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>BRGLD</th>\n",
       "      <td>0.591602</td>\n",
       "      <td>0.515622</td>\n",
       "      <td>0.657364</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>MNRHS</th>\n",
       "      <td>0.150281</td>\n",
       "      <td>0.137429</td>\n",
       "      <td>0.059683</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             f1        f2        f3\n",
       "DMIQP  0.149764  0.530645  0.568934\n",
       "VZJDZ  0.650494  0.085542  0.449133\n",
       "JZISA  0.959627  0.070090  0.220922\n",
       "BRGLD  0.591602  0.515622  0.657364\n",
       "MNRHS  0.150281  0.137429  0.059683"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "factors = DataFrame({'f1': fac1, 'f2': fac2, 'f3': fac3},\n",
    "                    index=ticker_subset)\n",
    "factors.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "f1    0.418460\n",
       "f2   -0.676459\n",
       "f3    0.230189\n",
       "dtype: float64"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "factors.corrwith(port) # 相关系数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# pd.ols(y=port, x=factors).beta 遗憾的是pandas升级把ols踢掉了，我们只能依靠sklearn。\n",
    "def beta_exposure(port, factors):\n",
    "    lr = LinearRegression()\n",
    "    y = port.as_matrix()\n",
    "    x = factors.as_matrix()\n",
    "    lr.fit(x, y) # 实际上就是把因子系数还原出来\n",
    "    return np.append(lr.coef_, lr.intercept_) # coef_是系数数组，intercept_是常数截距。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.68795968, -1.18575378,  0.38915681,  0.4397482 ])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "beta_exposure(port, factors)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "FINANCIAL: [ 0.69629311 -1.22427684  0.3611382   0.46239374]\n",
      "TECH: [ 0.67928687 -1.15298132  0.41722053  0.41948588]\n"
     ]
    }
   ],
   "source": [
    "for name, group in port.groupby(industries): # 书上的代码不要指望，不工作的，因为数组大小不匹配。如果你手工调整也是可以的。\n",
    "    factors_ = factors.loc[group.index,]\n",
    "    port_ = port.loc[group.index,]\n",
    "    beta = beta_exposure(port_, factors_)\n",
    "    print(name + ': ' + str(beta))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 十分位和四分位分析"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>open</th>\n",
       "      <th>high</th>\n",
       "      <th>close</th>\n",
       "      <th>low</th>\n",
       "      <th>volume</th>\n",
       "      <th>price_change</th>\n",
       "      <th>p_change</th>\n",
       "      <th>ma5</th>\n",
       "      <th>ma10</th>\n",
       "      <th>ma20</th>\n",
       "      <th>v_ma5</th>\n",
       "      <th>v_ma10</th>\n",
       "      <th>v_ma20</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2015-01-05</th>\n",
       "      <td>2.580</td>\n",
       "      <td>2.655</td>\n",
       "      <td>2.622</td>\n",
       "      <td>2.555</td>\n",
       "      <td>15964693.0</td>\n",
       "      <td>0.070</td>\n",
       "      <td>2.74</td>\n",
       "      <td>2.587</td>\n",
       "      <td>2.587</td>\n",
       "      <td>2.587</td>\n",
       "      <td>16572601.50</td>\n",
       "      <td>16572601.50</td>\n",
       "      <td>16572601.50</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-06</th>\n",
       "      <td>2.600</td>\n",
       "      <td>2.651</td>\n",
       "      <td>2.592</td>\n",
       "      <td>2.561</td>\n",
       "      <td>15561868.0</td>\n",
       "      <td>-0.030</td>\n",
       "      <td>-1.14</td>\n",
       "      <td>2.589</td>\n",
       "      <td>2.589</td>\n",
       "      <td>2.589</td>\n",
       "      <td>16235690.33</td>\n",
       "      <td>16235690.33</td>\n",
       "      <td>16235690.33</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-07</th>\n",
       "      <td>2.575</td>\n",
       "      <td>2.622</td>\n",
       "      <td>2.588</td>\n",
       "      <td>2.558</td>\n",
       "      <td>8887969.0</td>\n",
       "      <td>-0.004</td>\n",
       "      <td>-0.15</td>\n",
       "      <td>2.589</td>\n",
       "      <td>2.589</td>\n",
       "      <td>2.589</td>\n",
       "      <td>14398760.00</td>\n",
       "      <td>14398760.00</td>\n",
       "      <td>14398760.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-08</th>\n",
       "      <td>2.599</td>\n",
       "      <td>2.610</td>\n",
       "      <td>2.518</td>\n",
       "      <td>2.510</td>\n",
       "      <td>7936625.0</td>\n",
       "      <td>-0.070</td>\n",
       "      <td>-2.71</td>\n",
       "      <td>2.574</td>\n",
       "      <td>2.574</td>\n",
       "      <td>2.574</td>\n",
       "      <td>13106333.00</td>\n",
       "      <td>13106333.00</td>\n",
       "      <td>13106333.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-09</th>\n",
       "      <td>2.510</td>\n",
       "      <td>2.644</td>\n",
       "      <td>2.524</td>\n",
       "      <td>2.496</td>\n",
       "      <td>11561505.0</td>\n",
       "      <td>0.006</td>\n",
       "      <td>0.24</td>\n",
       "      <td>2.569</td>\n",
       "      <td>2.566</td>\n",
       "      <td>2.566</td>\n",
       "      <td>11982532.00</td>\n",
       "      <td>12848861.67</td>\n",
       "      <td>12848861.67</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             open   high  close    low      volume  price_change  p_change  \\\n",
       "date                                                                         \n",
       "2015-01-05  2.580  2.655  2.622  2.555  15964693.0         0.070      2.74   \n",
       "2015-01-06  2.600  2.651  2.592  2.561  15561868.0        -0.030     -1.14   \n",
       "2015-01-07  2.575  2.622  2.588  2.558   8887969.0        -0.004     -0.15   \n",
       "2015-01-08  2.599  2.610  2.518  2.510   7936625.0        -0.070     -2.71   \n",
       "2015-01-09  2.510  2.644  2.524  2.496  11561505.0         0.006      0.24   \n",
       "\n",
       "              ma5   ma10   ma20        v_ma5       v_ma10       v_ma20  \n",
       "date                                                                    \n",
       "2015-01-05  2.587  2.587  2.587  16572601.50  16572601.50  16572601.50  \n",
       "2015-01-06  2.589  2.589  2.589  16235690.33  16235690.33  16235690.33  \n",
       "2015-01-07  2.589  2.589  2.589  14398760.00  14398760.00  14398760.00  \n",
       "2015-01-08  2.574  2.574  2.574  13106333.00  13106333.00  13106333.00  \n",
       "2015-01-09  2.569  2.566  2.566  11982532.00  12848861.67  12848861.67  "
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data = ts.get_hist_data('510050',start='2015-01-01',end='2016-12-31')\n",
    "data.index = pd.to_datetime(data.index)\n",
    "data = data[::-1]\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 计算收益率\n",
    "px = data['close']\n",
    "returns = px.pct_change()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0     NaN\n",
       "1     NaN\n",
       "2     6.0\n",
       "3    10.0\n",
       "4    15.0\n",
       "5    20.0\n",
       "6    25.0\n",
       "7    30.0\n",
       "dtype: float64"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 先简单介绍一下rolling（移动窗口）函数\n",
    "# - window: 窗口的大小\n",
    "# - min_periods：最小的观察数值个数\n",
    "s = Series([1, 2, 3, 4, 5, 6, 7, 8])\n",
    "r = s.rolling(window=5, min_periods=3).sum()\n",
    "r\n",
    "# 输出如下\n",
    "# 0     NaN\n",
    "# 1     NaN\n",
    "# 2     6.0 sum(1...3)\n",
    "# 3    10.0 sum(1...4)\n",
    "# 4    15.0 sum(1...5)\n",
    "# 5    20.0 sum(2...6)\n",
    "# 6    25.0 sum(3...7)\n",
    "# 7    30.0 sum(4...8)\n",
    "# dtype: float64"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def to_index(rets):\n",
    "    index = (1 + rets).cumprod()\n",
    "    # 书里的代码不对，重写了。\n",
    "    # 因为前面用了移动窗口函数，所以这里first_loc是找到第一个数值不为NA的索引的位置。\n",
    "    first_loc = max(index.notnull().argmax() - Day(1), index.index[0])\n",
    "    index[first_loc] = 1\n",
    "    return index\n",
    "\n",
    "def trend_signal(rets, lookback, lag):\n",
    "    signal = rets.rolling(window=lookback, min_periods=lookback - lag).sum()\n",
    "    return signal.shift(lag)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\ProgramData\\Anaconda3\\lib\\site-packages\\ipykernel\\__main__.py:2: FutureWarning: \n",
      ".resample() is now a deferred operation\n",
      "You called resample(...) on this deferred object which materialized it into a series\n",
      "by implicitly taking the mean.  Use .resample(...).mean() instead\n",
      "  from ipykernel import kernelapp as app\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "date\n",
       "2015-06-22         NaN\n",
       "2015-06-23    0.008677\n",
       "2015-06-24    0.004675\n",
       "2015-06-25   -0.009195\n",
       "2015-06-26   -0.022823\n",
       "2015-06-29   -0.002663\n",
       "2015-06-30    0.017957\n",
       "2015-07-01   -0.011688\n",
       "2015-07-02   -0.002634\n",
       "2015-07-03   -0.008878\n",
       "Name: close, dtype: float64"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "signal = trend_signal(returns, 100, 3) # 累加100天的收益率\n",
    "trade_friday = signal.resample('W-FRI').resample('B').ffill() # 重采样到每个工作日周五\n",
    "trade_rets = trade_friday.shift(1) * returns # 计算周五买进的收益率\n",
    "trade_rets[120:130]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.axes._subplots.AxesSubplot at 0x1d977610a90>"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1d97761fe80>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "to_index(trade_rets).plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 书里代码不对，用returns的话后面groupby长度不匹配啊。。。\n",
    "vol = trade_rets.rolling(window=250, min_periods=200).std() * np.sqrt(250)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def sharpe(rets, ann=250): # 计算夏普率，定义自己网上查\n",
    "  return rets.mean() / rets.std()  * np.sqrt(ann)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "close\n",
       "(0.0161, 0.0232]   -0.339051\n",
       "(0.0232, 0.0401]    0.682121\n",
       "(0.0401, 0.0521]    2.242032\n",
       "(0.0521, 0.0715]   -0.146591\n",
       "Name: close, dtype: float64"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "trade_rets.groupby(pd.qcut(vol, 4)).agg(sharpe)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
